package http;

import data.DataHandler;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.URLDecoder;
import java.util.Date;

/**
 * Class that handle HTTP Transactions
 * @author lailiaidi
 */
public class HTTPserver extends Thread {

    private String obStrServerAddr;
    private int obStrPort;
    private String CRLF = "\r\n";
    private String emailData = null;
    private DataHandler obDataHandler;

    public HTTPserver(Socket client, String obStrServerAddr, int obStrPort, DataHandler obDataHandler) {
        this.client = client;
        this.obStrServerAddr = obStrServerAddr;
        this.obStrPort = obStrPort;
        this.obDataHandler = obDataHandler;
    }
    private PrintStream output = null;
    private BufferedReader input = null;
    private Socket client = null;

    /* In this method we process the packet and petitions to send to the smtp  server */
    @Override
    public void run() {
        try {
            System.out.println("INFO: Client " + client.getInetAddress() + ":"
                    + client.getPort() + " is connected");

            output = new PrintStream(client.getOutputStream());
            input = new BufferedReader(new InputStreamReader(client.getInputStream()));

            String currentLine = input.readLine();
            if (requestType(currentLine)) {
                if (requestProcessing(currentLine).equals("/index.html")
                        || requestProcessing(currentLine).equals("/")) {
                    /* The default home page */
                    sendResponse(true, INDEX_PAGE);
                } else if (requestProcessing(currentLine).equals("/input.html")) {
                    /* The default home page */
                    sendResponse(true, SUBMISSION_PAGE);
                } else {
                    emailData = getForm(requestProcessing(currentLine));
                    if (emailData != null && emailData.length() > 0) {
                        /* We only call this part after client submit the mail data, at the second GET method request */
                        if (emailData.contains("btnChange=Change")) {
                            sendResponse(true, SUBMISSION_PAGE);
                        } else if (emailData.contains("btnReset=Delete")) {
                            if (obDataHandler.isAnyCurrentMessage()) {
                                // The data is valid, Send response to the
                                // client about the successfully delete message
                                obDataHandler.setTempData("");
                                sendResponse(true, SUCCESS_DELETE_PAGE);
                            } else {
                                // Send response FAILED to client
                                sendResponse(true, FAILED_DELETE_PAGE);
                            }
                        } else if (emailData.contains("new") && emailData.contains("btnSubmit=Submit")) {
                            if (obDataHandler.isValidHTTPData(emailData)) {
                                // The data is valid, Send response to the client about the successfully sending message
                                // We change the temp data first, to provide multithread
                                obDataHandler.setTempData(emailData);
                                sendResponse(true, SUCCESS_PAGE);
                            } else {
                                // Send response FAILED to client
                                sendResponse(true, FAILED_PAGE);
                            }
                        } else if (emailData.contains("btnBack=Cancel")) {
                            sendResponse(true, INDEX_PAGE);
                        }
                    } else {
                        sendResponse(false, WRONG_PAGE);
                    }
                }
            }// end if
            else {
                System.err.println("ERROR: Invalid request");
                sendResponse(false, WRONG_PAGE);
            }
            emailData = null;
        } catch (Exception e) {
            System.err.println("ERROR: Exception happens");
        }
    }

    private String getForm(String text) {
        String emailFields = "";
        try {
            emailFields = URLDecoder.decode(text, "UTF-8");
        } catch (Exception e) {
            return null;
        }
        return emailFields;
    }

    /* Method used to check in the received query is GET. In that case, it
     * returns true, otherwise false
     */
    private Boolean requestType(String request) {
        if (request.regionMatches(true, 0, "GET ", 0, 4)) {
            return true;
        }
        return false;
    }

    /* Method to obtain the requested file in the query */
    private String requestProcessing(String request) {
        try {
            int fsp = request.indexOf(' ');
            int nsp = request.indexOf(' ', fsp + 1);
            String file = request.substring(fsp + 1, nsp);
            if (file.equals("/index.htm")) {
                return null;
            } else {
                return file;
            }
        } catch (Exception e) {
            return null;
        }

    }// end of method

    /* method to reply with a code 200 OK */
    private String reply(boolean isOk) {
        String reply = "";
        if (isOk) {
            reply = "HTTP/1.1 200 OK";
        } else {
            reply = "HTTP/1.1 404 Not Found";
        }
        return reply;
    }
    private final int INDEX_PAGE = 0;
    private final int SUBMISSION_PAGE = 1;
    private final int WRONG_PAGE = 2;
    private final int SUCCESS_PAGE = 3;
    private final int FAILED_PAGE = 4;
    private final int SUCCESS_DELETE_PAGE = 5;
    private final int FAILED_DELETE_PAGE = 6;

    private void sendResponse(boolean isOk, int request) throws Exception {
        String responseString = "";
        String obTempData = obDataHandler.getTempData();
        switch (request) {
            case INDEX_PAGE:
                if (obTempData == null || obTempData.length() == 0) {
                    responseString = headHTML()
                            + bodyCurrentHTML(obDataHandler.getNoMessageText(), null, false);
                } else {
                    /* We use obDataHandler.getHTTPData(emailData) to remedy other
                     * possibility of waiting stage on updating message */
                    responseString = headHTML()
                            + bodyCurrentHTML(obTempData, null, false);
                }
                break;
            case SUBMISSION_PAGE:
                responseString = headHTML() + bodySubmissionHTML();
                break;
            case SUCCESS_PAGE:
                responseString = headHTML()
                        + bodyCurrentHTML(obTempData,
                        "The message has been successfully updated", true);
                break;
            case FAILED_PAGE:
                if (obTempData == null | obTempData.length() == 0) {
                    responseString = headHTML()
                            + bodyCurrentHTML(obDataHandler.getNoMessageText(),
                            "You must insert valid message", true);
                } else {
                    responseString = headHTML()
                            + bodyCurrentHTML(obTempData,
                            "You must insert valid message", true);
                }
                break;
            case SUCCESS_DELETE_PAGE:
                responseString = headHTML() + bodyCurrentHTML(obDataHandler.getNoMessageText(),
                        "The message has been successfully deleted", true);
                break;
            case FAILED_DELETE_PAGE:
                responseString = headHTML()
                        + bodyCurrentHTML(obDataHandler.getNoMessageText(),
                        "There is no message in the system that can be deleted",
                        true);
                break;
            case WRONG_PAGE:
                responseString = headHTML() + bodyHTMLWrongPage();
                break;
        }

        output.println(reply(isOk));
        output.println(addHeader(responseString.length()));
        output.println(responseString);
        output.flush();
        System.out.println("INFO: Closing HTTP connection");
        output.close();
        input.close();
        client.close();

        boolean isFinish = false;
        //After the data is flushed, we try to submit the data to the real variable on the server
        if (request == SUCCESS_PAGE || request == SUCCESS_DELETE_PAGE) {
            isFinish = obDataHandler.setCurrentMessage(emailData, this);
        }
        if (isFinish) {
            Thread.currentThread().stop();
        }
    }

    private String addHeader(int contentLength) {
        Date d = new Date();
        String header = "Date: " + d.toString() + CRLF
                + "Content-Type: text/html" + CRLF + "Content-Length: "
                + contentLength + CRLF;
        return header;
    }

    private String headHTML() {
        String head = "<HTML>"
                + "<HEAD>"
                + "<TITLE>IK2213 VoIP Assignment</TITLE>"
                + "<META http-equiv=Content-Type content=\"text/html; charset=UTF8\">"
                + "<META content=\"MSHTML 6.00.2900.5512\" name=GENERATOR>"
                + "<script type=\"text/javascript\">" + "</script>" + "</HEAD>";
        return head;
    }

    private String bodyHTMLWrongPage() {
        String body = "<BODY>+"
                + "<H1 align=center>IK2213 VoIP Assignment</H1>"
                + "<H4 align=center>The page that you reques is not available, please go to <a href=\"http://"
                + obStrServerAddr + ":" + obStrPort + "/index.html\">http://"
                + obStrServerAddr + ":" + obStrPort + "/index.html</a></H4>"
                + "</BODY>";
        return body;
    }

    private String bodyCurrentHTML(String obStrCurrentMessage,
            String obStrConfirmMessage, boolean isConfirmation) {
        String body = "";
        if (!isConfirmation) {
            body = "<BODY>";
        } else {
            body = "<BODY onload='alert(\"" + obStrConfirmMessage + "\");'>";
        }
        body += "<H1 align=center>VoIP Message Main Page </H1>"
                + "<form name=formWebmail method=\"get\" action=\"http://"
                + obStrServerAddr
                + ":"
                + obStrPort
                + "\">"
                + "<table align=\"center\"><tr>"
                + "<td height=\"177\"><b>Current Message </b></td>"
                + "<td><label for=\"current\"></label>"
                + "<textarea name=\"current\" id=\"current\" cols=\"45\" rows=\"10\" disabled>"
                + obStrCurrentMessage
                + "</textarea></td>"
                + "</tr></table><table width=\"50%\" border=\"0\" align=\"center\">"
                + "<tr><th scope=\"col\"><INPUT type=submit value=Change name=btnChange align=\"center\">"
                + "<INPUT type=submit value=Delete name=btnReset align=\"center\"></th>"
                + "</tr></table></form></body></HTML>";
        return body;
    }

    private String bodySubmissionHTML() {
        String body = "";

        body += "<H1 align=center>VoIP Message Submission Page </H1>"
                + "<form name=formWebmail method=\"get\" action=\"http://"
                + obStrServerAddr
                + ":"
                + obStrPort
                + "\">"
                + "<table align=\"center\">"
                + "<tr><td height=\"184\"><b>New Message </b></td>"
                + "<td><label for=\"new\"></label>"
                + "<textarea name=\"new\" id=\"new\" cols=\"45\" rows=\"10\"></textarea></td>"
                + "</tr></table>"
                + "<table width=\"50%\" border=\"0\" align=\"center\">"
                + "<tr>"
                + "<th scope=\"col\"><label for=\"btnSubmit\"></label><input type=\"submit\" name=\"btnSubmit\" id=\"btnSubmit\" value=\"Submit\">"
                + "</th><th scope=\"col\"><label for=\"btnReset\"></label><input type=\"submit\" name=\"btnReset\" id=\"btnReset\" value=\"Reset\">"
                + "</th><th scope=\"col\"><label for=\"btnBack\"></label><input type=\"submit\" name=\"btnBack\" id=\"btnBack\" value=\"Cancel\"></th>"
                + "</tr></table></form></body></HTML>";
        return body;
    }
}// class end

